package com.autonavi.notify.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.annotation.PostConstruct;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.autonavi.notify.dao.NotifyDao;
import com.autonavi.notify.entity.Config;
import com.autonavi.notify.entity.Notify;
import com.autonavi.notify.entity.User;

@Service
@Lazy(value=false)
public class NotifyService {
	
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private NotifyDao notifyDao;
	
	@Autowired
	private ConfigService configService;
	
	@Autowired
	private UserService userService;
	
	ExecutorService threadPool;
	
	private Map<String,String> mailConfigCache = new HashMap<String, String>();
	
	private Map<String,User> userCache = new HashMap<String, User>();
	
	@PostConstruct
	public void init(){
		threadPool = Executors.newFixedThreadPool(10);
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true){
					try{
						loadToCache();
						Thread.sleep(60000);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	
	
	public void loadToCache(){
		mailConfigCache = configService.getMailConfig();
		Map<String,User> map = new HashMap<String, User>();
		List<User> users = userService.findAll();
		for(User user : users){
			String rq = user.getRequestCode();
			if(!StringUtils.isBlank(rq)){
				String[] codes = rq.split(",");
				for(String code : codes){
					map.put(code,user);
				}
			}
		}
		userCache = map;
	}
	@Transactional
	public Notify save(final Notify notify){
		if(StringUtils.isBlank(notify.getId())){
			notify.setId(UUID.randomUUID().toString());
		}
		Notify result = notifyDao.save(notify);
		
		if(mailConfigCache.size()>0&&userCache.containsKey(notify.getRequestCode())){
			final User user = userCache.get(notify.getRequestCode());
			threadPool.submit(new Runnable() {
				@Override
				public void run() {
					try{
					sendMail(mailConfigCache.get("smtpHost"),mailConfigCache.get("smtpPort"),"true".equals(mailConfigCache.get("useSSL"))
							,mailConfigCache.get("smtpAccout"),mailConfigCache.get("smtpPassword")
							,user.getEmail()
							,notify.getRequestCode(),notify.getContent());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		}
		return result;
	}
	
	@Transactional(readOnly=true)
	public Page<Notify> findAll(String requestCode,int pageNumber){
		return notifyDao.findAll("%"+requestCode+"%",new PageRequest(pageNumber, 10,Direction.DESC,"timestamp"));
	}
	
	public void sendMail(String smtpHost,String smtpPort,boolean useSSL,final String mailAccount,final String mailPassword,String mailAddress,String mailTitle,String mailBody) throws Exception {
			Properties props = new Properties();
			props.put("mail.smtp.host", smtpHost);
			props.put("mail.smtp.auth", "true");
			props.put("mail.smtp.timeout","15000");
			props.put("mail.smtp.port",smtpPort);
			if(useSSL){
				props.put("mail.smtp.socketFactory.port", smtpPort);
				props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
				props.put("mail.smtp.socketFactory.fallback", "false");
				props.put("mail.smtp.starttls.enable","true");
			}
			Session session = Session.getInstance(props, new Authenticator() {
				@Override
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(mailAccount,mailPassword);
				}
			});
			
			session.getProperties().putAll(props);
			MimeMessage msg = new MimeMessage(session);
			msg.setSentDate(new Date());
			InternetAddress fromAddress = new InternetAddress(mailAccount,smtpHost,"UTF-8");
			msg.setFrom(fromAddress);
			InternetAddress[] toAddress = new InternetAddress[1];
			toAddress[0] = new InternetAddress(mailAddress);
			msg.setRecipients(Message.RecipientType.TO, toAddress);
			msg.setSubject(mailTitle);  
			msg.setText(mailBody, "UTF-8");
			msg.saveChanges();
			Transport.send(msg);
	}
	
}
